package com.yulian.web_api.system_management;

import java.util.ArrayList; 
import java.util.List;

import com.yulian.repository.CommonRepositoryImpl; 
import com.yulian.util.PBKDF2_OK;

import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.Log4JLoggerFactory; 
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.JWTOptions; 
import io.vertx.ext.auth.jwt.JWTAuth; 
import io.vertx.pgclient.PgPool;
import io.vertx.sqlclient.Row;
import io.vertx.sqlclient.RowSet;
import io.vertx.sqlclient.SqlConnection;
import io.vertx.sqlclient.Tuple; 
/**
 * 该类完成用户的注册，用户登录功能
 * @author  
 */
public class UserManager {
	final InternalLogger logger = Log4JLoggerFactory.getInstance(UserManager.class); 
	CommonRepositoryImpl commonRepository = new CommonRepositoryImpl(); 
	/**
	 * 获取数据库链接
	 * @param client
	 * @return
	 */
	public Future<SqlConnection> getCon(PgPool client){
		Promise<SqlConnection> promise = Promise.promise();
		client.getConnection(ar1 -> {
			if (ar1.succeeded()) { 
				SqlConnection conn = ar1.result();
				promise.complete(conn);
			} else {
				logger.info("Connection 失败: {}",ar1.cause().getMessage()); 
		        promise.fail(ar1.cause());  //这里就相当于继续向上抛出异常，用Promise来向上抛异常 
			}
		});
		return promise.future();
	} 
	 
	/**
	 *  实现用户登录功能
	 * @param client
	 * @param jwt
	 * @param bodyJSObj
	 * @return
	 */
	public Future<JsonObject> webSignin(PgPool client, JWTAuth jwt, JsonObject bodyJSObj) {
		Promise<JsonObject> promise = Promise.promise();
		String phone = bodyJSObj.getString("phone");
		String password = bodyJSObj.getString("password"); 
		if (phone != null && password != null) { 
			this.getCon(client)
			.compose(conn -> this.getUserByPhone(conn, phone))                  
			.onSuccess(rows -> {                                              // 第一层 lamda
				List<JsonObject> list = new ArrayList<JsonObject>();  
				if( rows.size() >= 1) { 
					rows.forEach(item -> { 
						JsonObject json =  new JsonObject();
						json.put("id", item.getValue("id")); 
						json.put("salt", item.getValue("salt"));
						json.put("password", item.getValue("password")); 
						list.add(json); 
					});
					JsonObject userJson = list.get(0);
					int user_id = userJson.getInteger("id");
					String salt = userJson.getString("salt");
				 
					String exist_encryped_password =  userJson.getString("password");  
					String encryped_password = PBKDF2_OK.getPBKDF2(password, salt);
					if (encryped_password.equals(exist_encryped_password)) {
						 
						// 开始查询数据库返回对应用户的权限列表
						this.getCon(client)
						.compose(con2 -> this.getUserPerms(con2, user_id))                  
						.onSuccess(rows2 -> {
							JsonArray perms = new JsonArray();
							JsonArray roles = new JsonArray();
							rows2.forEach(item -> { 
							 
								if (item.getValue("perm").toString().contains("role:")) {
									roles.add(item.getValue("perm")); 
								} else {
									perms.add(item.getValue("perm"));
								}
							});
							// 返回token
							JsonObject authos = new JsonObject().put("permissions", perms).put("role", roles).put("username",phone).put("userId", user_id);
							logger.info("authos: "+ authos.toString());
							String token = jwt.generateToken(authos,
									new JWTOptions().setIgnoreExpiration(false).setExpiresInMinutes(30000).setAlgorithm("RS256"));
							JsonObject result_json = new JsonObject();
							result_json.put("token", token).put("code", 0).put("msg", "登录成功");
							promise.complete(result_json);
							 
						}); 
						 
					} else {
						JsonObject json = new JsonObject();
						json.put("code", -1);
						json.put("message","401 error");  
						promise.complete(json); 
					} 
				}  
			})
			.onFailure(throwable -> {
	              //真实的项目开发中，我们可以在这里捕获Future+Promise异步链式调用的异常
	              //在这里统一处理，比如写入日志文件
				JsonObject json = new JsonObject();
				json.put("code", -1);
				json.put("message",throwable.toString());  
				promise.complete(json);
			});  		
		} 
		return promise.future();
	}  
	
	/**
	 * 根据用户的手机号查询用户信息 
	 * @param conn
	 * @param phone
	 * @return
	 */
	public Future<RowSet<Row>> getUserByPhone(SqlConnection conn, String phone){
		Promise<RowSet<Row>> promise = Promise.promise();
	    conn
	    .preparedQuery("select id,   phone, salt, password  from users where phone = $1")
	    .execute(Tuple.of(phone), ar2 -> {
	        //Release the connection to the pool
	    	conn.close();
	        if(ar2.succeeded()){
	          logger.info("getUserByPhone, query success: "+ ar2.result().rowCount());
	          promise.complete(ar2.result());
	        }else{
	        	logger.info("getUserByPhone, 失败: {}", ar2.cause().getMessage());	
	        	//用Promise来向上抛异常
	        	promise.fail(ar2.cause());
	        }
	    });
	    return promise.future();
	} 
	
	/**
	 * 获取用户的权限
	 * @param conn
	 * @param user_id
	 * @return
	 */
	public Future<RowSet<Row>> getUserPerms(SqlConnection conn, int user_id){
		Promise<RowSet<Row>> promise = Promise.promise();
 
		String user_perms_sql = " SELECT distinct a.perm FROM  perms a left join roles_perms b on (a.id=b.perm_id) left join users_roles c  on ( b.role_id = c.role_id ) "+ 
				" left join users d on ( c.user_id = d.id )  where d.id = $1 and a.is_delete = 0 "; 
		conn
		.preparedQuery(user_perms_sql)
		.execute(Tuple.of(user_id), ar2 -> {
	        //Release the connection to the pool
			conn.close();
	        if(ar2.succeeded()){
	          logger.info("getUserPerms, query success: "+ ar2.result().rowCount());
	          promise.complete(ar2.result());
	        }else{
	        	logger.info("getUserPerms, 失败: {}", ar2.cause().getMessage());	
	        	//用Promise来向上抛异常
	        	promise.fail(ar2.cause());
	        }
		});
	    return promise.future();
	}   
	

} 